package com.black.platform.menu.service.handler.impl;

import com.black.common.vo.MenuVo;
import com.black.platform.menu.po.Menu;
import com.black.platform.menu.service.biz.MenuService;
import com.black.platform.menu.service.handler.MenuHandlerService;
import com.black.platform.permission.service.bz.PermissionService;
import com.black.common.vo.PermissionVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MenuHandlerServiceImpl implements MenuHandlerService {


    private final PermissionService permissionService;

    private final MenuService menuService;

    @Override
    @Cacheable(cacheNames = "UserMenu")
    public List<MenuVo> getMenuByRequestUserId(Long userId, String systemCode) {
        List<PermissionVo> permissionList = permissionService.getAllPermissionsByUser(userId, systemCode, false);
        List<Long> menuIds = permissionList.stream().filter(permission -> "menu".equals(permission.getPermissionType()))
                .distinct().map(PermissionVo::getMenuId).collect(Collectors.toList());
        if (menuIds.size() > 0) {
            List<Menu> menuList = menuService.listByIds(menuIds);
            return buildMenuTree(menuList);
        }
        return new ArrayList<>();
    }

    @Override
    public List<MenuVo> search(String systemCode) {
        List<Menu> menuList = menuService.search(systemCode);
        return buildMenuTree(menuList);
    }

    /**
     * 构建菜单树
     *
     * @param menuList 菜单集合
     * @return 菜单树
     */
    private List<MenuVo> buildMenuTree(List<Menu> menuList) {
        Map<Long, MenuVo> menuVoMap = menuList.stream().collect(Collectors.toMap(Menu::getId, menu -> {
            MenuVo menuVo = new MenuVo();
            BeanUtils.copyProperties(menu, menuVo);
            return menuVo;
        }));
        menuList.sort(Comparator.comparingInt(Menu::getOrders));
        List<MenuVo> menuVoList = new ArrayList<>();
        for (Menu menu : menuList) {
            if (menu.getParentId() == null) {
                menuVoList.add(menuVoMap.get(menu.getId()));
            } else {
                if (menuVoMap.get(menu.getParentId()).getChildren() == null) {
                    menuVoMap.get(menu.getParentId()).setChildren(new ArrayList<>());
                }
                menuVoMap.get(menu.getParentId()).getChildren().add(menuVoMap.get(menu.getId()));
            }
        }
        return menuVoList;
    }
}
